package com.protocols.sctp.m3ua.sccp;

import java.io.Serializable;

import com.protocols.BCDNumber;
import com.protocols.BinaryInteger;
import com.protocols.OctaveInteger;
import com.protocols.ProtoOperations;
import com.protocols.ProtocolStackException;
import com.protocols.sctp.m3ua.ProtocolData;

public class CallPartyAddress implements Serializable{

	
	private BinaryInteger RoutingIndicator = new BinaryInteger(1, 6);
	private BinaryInteger GTIndicator = new BinaryInteger(4, 2);
	private BinaryInteger SSNIndicator = new BinaryInteger(1, 1);
	private BinaryInteger PointCodeIndicator = new BinaryInteger(1, 0);
	private OctaveInteger SubSystemNumber = new OctaveInteger(1);
	private OctaveInteger PointCode = new OctaveInteger(2);
	private OctaveInteger GTTranslationType = new OctaveInteger(1);
	private BinaryInteger GTNumPlan = new BinaryInteger(4, 4);
	private BinaryInteger GTNatureOfAddress = new BinaryInteger(7, 0);
	private BCDNumber GlobalTitle = new BCDNumber("f");
	
	public CallPartyAddress() {
				
	}
	public byte [] getByteArray(){	
		byte [] addressindicator = {(byte)(RoutingIndicator.getOffsetValue()|GTIndicator.getOffsetValue()|SSNIndicator.getOffsetValue()|PointCodeIndicator.getOffsetValue())};
		return  ProtoOperations.concatArrays(addressindicator,(getPointCodeIndicator()==1?ProtoOperations.ReverseByteArray(PointCode.getByteArray()):new byte [0]), (getSSNIndicator()==1?SubSystemNumber.getByteArray():new byte [0]), getGTBytes());
	}
	
	public void setRoutingIndicator(int routingindicator){		
		RoutingIndicator.setValue(routingindicator);
	}
	
	public int getRoutingIndicator(){		
		return RoutingIndicator.getValue();	
	}
	
	public void setGTIndicator(int gtindicator){
		GTIndicator.setValue(gtindicator);
	}
	
	public int getGTIndicator(){

		return GTIndicator.getValue();		
	}
	
	
	public int getSSNIndicator(){		
		return SSNIndicator.getValue();
	}
	
	public void setSSNIndicator(int ssnindicator){		
		SSNIndicator.setValue(ssnindicator);
	}

	public int getPointCodeIndicator() {
		return PointCodeIndicator.getValue();
	}

	public void setPointCodeIndicator(int pointCodeIndicator) {
		PointCodeIndicator.setValue(pointCodeIndicator);
	}

	
	public int getGTNatureOfAddress() {
		return GTNatureOfAddress.getValue();
	}

	public void setGTNatureOfAddress(int GTNatureOfAddress) {
		this.GTNatureOfAddress.setValue(GTNatureOfAddress);
	}

	public int getGTTranslationType() {
		return GTTranslationType.Value;
	}

	public void setGTTranslationType(int GTTranslationType) {
		this.GTTranslationType.Value = GTTranslationType;
	}

	public String getGlobalTitle() {
		return GlobalTitle.getValue();
	}

	public void setGlobalTitle(String globalTitle) {
		GlobalTitle.setValue(globalTitle);
	}
	public void setGlobalTitle(byte [] globaltitle, Boolean odd) {
		GlobalTitle.setValue(globaltitle,odd);
	}
	
	private byte [] getGTBytes(){
		if (getGTIndicator()==0)
			return new byte[0];
		else if (getGTIndicator()==1)
		{
			int oddeven = (new BinaryInteger((GlobalTitle.getValue().length()%2),1,7)).getOffsetValue();
			byte [] oddevenNatureofadd= {(byte)(oddeven| GTNatureOfAddress.getOffsetValue())};
			return ProtoOperations.concatArrays(oddevenNatureofadd, GlobalTitle.getByteArray());
		}
		else if (getGTIndicator()==2)
			return GTTranslationType.getByteArray();
		else if (getGTIndicator()==3)
		{
			int oddeven=( GlobalTitle.getValue().length()%2==1?1:2);
			byte [] NumberingPlanEncoding= {(byte)(GTNumPlan.getOffsetValue()| oddeven)};
			return ProtoOperations.concatArrays(GTTranslationType.getByteArray(),NumberingPlanEncoding, GlobalTitle.getByteArray());
		}
		else // 4
		{
			int oddeven = GlobalTitle.getValue().length()%2==1?1:2;
			byte [] NumberingPlanEncoding= {(byte)(GTNumPlan.getOffsetValue()| oddeven)};
			byte[] natureofadd= {(byte)GTNatureOfAddress.getOffsetValue()};
			return ProtoOperations.concatArrays(GTTranslationType.getByteArray(),NumberingPlanEncoding,natureofadd, GlobalTitle.getByteArray());
		}
		
		
	}
	public int getGTNumPlan() {
		return GTNumPlan.getValue();
	}
	public void setGTNumPlan(int gTNumPlan) {
		GTNumPlan.setValue(gTNumPlan);
	}

	public int getLength(){
		return getByteArray().length;
		
	}
	public int getSubSystemNumber() {
		return SubSystemNumber.getValue();
	}
	public void setSubSystemNumber(int subSystemNumber) {
		SubSystemNumber.setValue(subSystemNumber);
		SSNIndicator.setValue(1);
	}
	public int getPointCode() {
		return PointCode.getValue();
	}
	public void setPointCode(int pointCode) {
		PointCode.setValue( pointCode);
		setPointCodeIndicator(1);
	}

	public byte [] decode(byte [] input) {
		int length=input[0];
		
			setRoutingIndicator((input[1]& 0b01000000)>>6);
			setGTIndicator((input[1]& 0b00111100)>>2);
			setSSNIndicator((input[1]& 0b00000010)>>1);
			setPointCodeIndicator((input[1]& 0b00000001));
			byte remainder[] =ProtoOperations.extractByteArray(input, length+1, input.length-length-1);
					
			byte [] GTData=new byte[0];
			if (getPointCodeIndicator()==1)
			{
				//setPointCode(ProtoOperations.intFromByteArray(input, 2, 2) );
				setPointCode(ProtoOperations.intFromByteArray(new byte[] {input[3],input[2]}, 0, 2) );
			}
			
			if (getPointCodeIndicator()==1 && getSSNIndicator()==1)
				setSubSystemNumber(input[4]&0xff);
			else if (getPointCodeIndicator()==0 && getSSNIndicator()==1)
				setSubSystemNumber(input[2]&0xff);
			
			
			if (getPointCodeIndicator()==1 && getSSNIndicator()==1 && getGTIndicator()>0)
				GTData=ProtoOperations.extractByteArray(input, 5, length-4);			
			else if (getPointCodeIndicator()==0 && getSSNIndicator()==1 && getGTIndicator()>0)
				GTData=ProtoOperations.extractByteArray(input, 3, length-2);		
			else if (getPointCodeIndicator()==0 && getSSNIndicator()==0 && getGTIndicator()>0)
				GTData=ProtoOperations.extractByteArray(input, 2, length-1);	
			else if (getPointCodeIndicator()==1 && getSSNIndicator()==0 && getGTIndicator()>0)
				GTData=ProtoOperations.extractByteArray(input, 4, length-3);	
			
			if (getGTIndicator()==1)
			{
				setGTNatureOfAddress(GTData[0]& 0b01111111);
				Boolean odd = (GTData[0]& 0b10000000)>>7==1 ? true:false;
				setGlobalTitle(ProtoOperations.extractByteArray(GTData, 1, GTData.length-1),odd);
			}
			else if (getGTIndicator()==2)
				setGTTranslationType(GTData[0]&0xff);
			else if (getGTIndicator()==3)
			{
				setGTTranslationType(GTData[0]&0xff);
				setGTNumPlan((GTData[1]&0b11110000)>>4);				
				Boolean odd=(GTData[1]&0b00001111) ==1;
				setGlobalTitle(ProtoOperations.extractByteArray(GTData, 2, GTData.length-2),odd);
			}
			else // 4
			{
				setGTTranslationType(GTData[0]&0xff);
				setGTNumPlan((GTData[1]&0b11110000)>>4);				
				Boolean odd=(GTData[1]&0b00001111) ==1;
				setGTNatureOfAddress(GTData[2]&0xff);
				setGlobalTitle(ProtoOperations.extractByteArray(GTData, 3, GTData.length-3),odd);
			}			
			
			return remainder;
		

			
		
		
	}	
	
}
